﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Geldtransporter
{
    class Transporter
    {
        private BagStack leftStack = new BagStack();
        private BagStack rightStack = new BagStack();

        internal BagStack RightStack
        {
            get { return rightStack; }
            set { rightStack = value; }
        }
        internal BagStack LeftStack
        {
            get { return leftStack; }
            set { leftStack = value; }
        }   

        public Transporter(BagStack bags)
        {
            foreach (var item in bags.BagList)
            {
                if (leftStack.TotalMoney() > rightStack.TotalMoney())
                {
                    rightStack.Add(item);
                }
                else
                {
                    leftStack.Add(item);
                }
            }           
        }



        public void OptimizeMoney()
        {

            //choose which side to optimize

            BagStack current;
            BagStack opposite;

            MoneyBag chosenBag = null;
          
            if (leftStack.TotalMoney() > rightStack.TotalMoney())
            {
                current = leftStack;
                opposite = rightStack;
            }
            else
            {
                current = rightStack;
                opposite = leftStack;
            }


            //chose which bag to switch
            int difference = current.TotalMoney() - opposite.TotalMoney();

            var query = from b in current.BagList
                        orderby Math.Abs(((difference/2) - b.Money)) ascending
                        select b;

            foreach (var item in query)
            {
                chosenBag = item;
                break;
            }

            //calculate money difference if switching
            int newDifference = Math.Abs((current.TotalMoney() - chosenBag.Money) - (opposite.TotalMoney() + chosenBag.Money));

            if (newDifference < Math.Abs(difference))
            {
                current.BagList.Remove(chosenBag);
                opposite.BagList.Add(chosenBag);
            }
            else
            {
                //no optimization possible anymore :( maybe we can switch a bag with one from the other side
                MoneyBag chosenCurrent = null;
                MoneyBag chosenOpposite = null;
                int best = Math.Abs(current.TotalMoney() - opposite.TotalMoney());
                foreach (var item in current.BagList)
	            {

		            var q = from o in opposite.BagList
                                orderby Math.Abs((current.TotalMoney() - item.Money + o.Money) - (opposite.TotalMoney() - o.Money + item.Money))
                                select o;

                    MoneyBag temp = null;
                    foreach (var opp in q)
                    {
                        temp = opp;
                        break;
                    }

                    newDifference = Math.Abs((current.TotalMoney() - item.Money + temp.Money) - (opposite.TotalMoney() - temp.Money + item.Money));

                    if (newDifference < difference)
                    {
                        best = newDifference;
                        chosenCurrent = item;
                        chosenOpposite = temp;
                    }
	            }

                if (chosenCurrent != null)
                {
                    current.BagList.Remove(chosenCurrent);
                    opposite.BagList.Add(chosenCurrent);

                    opposite.BagList.Remove(chosenOpposite);
                    current.BagList.Add(chosenOpposite);
                }                   

            }
        }

        public void OptimizeWeight()
        {
            //choose which side to optimize

            BagStack current;
            BagStack opposite;

            MoneyBag chosenBag = null;
            //chose which bag to switch
            if (leftStack.TotalWeight() > rightStack.TotalWeight())
            {
                current = leftStack;
                opposite = rightStack;
            }
            else
            {
                current = rightStack;
                opposite = leftStack;
            }

            //calculate weight

            int difference = current.TotalWeight() - opposite.TotalWeight();
            int moneyDifference = current.TotalMoney() - opposite.TotalMoney();

            var query = from b in current.BagList
                        where (Math.Abs((current.TotalMoney() - b.Money)-(opposite.TotalMoney() + b.Money)) <= 10000)
                        orderby b.Weight descending
                        select b;

            foreach (var item in query)
            {  
                    chosenBag = item;
                    break;
            }

            if(chosenBag != null)
            {
                current.BagList.Remove(chosenBag);
                opposite.BagList.Add(chosenBag);
            }
            

        }    
        
    }
}
